﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Dotnet.Utils.Utility.ObjectExtensions.Obj;

namespace Dotnet.Utils.Utility.ObjectExtensions.To
{
    public static class ConvertUtil
    {
        public static int ToInt(object input)
        {
            return ToIntOrNull(input) ?? 0;
        }

        /// <summary>
        /// 转换为32位可空整型
        /// </summary>
        /// <param name="input">输入值</param>
        public static int? ToIntOrNull(object input)
        {
            int value;
            bool flag = int.TryParse(input.ToSafeString(), out value);
            int? result;
            if (flag)
            {
                result = new int?(value);
            }
            else
            {
                try
                {
                    double? num = ToDoubleOrNull(input, new int?(0));
                    if (num == null)
                    {
                        result = null;
                    }
                    else
                    {
                        result = new int?(Convert.ToInt32(num));
                    }
                }
                catch
                {
                    result = null;
                }
            }
            return result;
        }

        public static long ToLong(object input)
        {
            return ToLongOrNull(input) ?? 0L;
        }

        public static long? ToLongOrNull(object input)
        {
            long value;
            bool flag = long.TryParse(input.ToSafeString(), out value);
            long? result;
            if (flag)
            {
                result = new long?(value);
            }
            else
            {
                try
                {
                    decimal? num = ToDecimalOrNull(input, new int?(0));
                    if (num == null)
                    {
                        result = null;
                    }
                    else
                    {
                        result = new long?(Convert.ToInt64(num));
                    }
                }
                catch
                {
                    result = null;
                }
            }
            return result;
        }

        public static float ToFloat(object input, int? digits = null)
        {
            float? num = ToFloatOrNull(input, digits);
            return num != null ? num.GetValueOrDefault() : 0f;
        }

        public static float? ToFloatOrNull(object input, int? digits = null)
        {
            float num;
            float? result;
            if (!float.TryParse(input.ToSafeString(), out num))
            {
                result = null;
            }
            else if (digits == null)
            {
                result = new float?(num);
            }
            else
            {
                result = new float?((float)Math.Round((double)num, digits.Value));
            }
            return result;
        }

        public static double ToDouble(object input, int? digits = null)
        {
            double? num = ToDoubleOrNull(input, digits);
            return num != null ? num.GetValueOrDefault() : 0.0;
        }

        public static double? ToDoubleOrNull(object input, int? digits = null)
        {
            double value;
            double? result;
            if (!double.TryParse(input.ToSafeString(), out value))
            {
                result = null;
            }
            else if (digits == null)
            {
                result = new double?(value);
            }
            else
            {
                result = new double?(Math.Round(value, digits.Value));
            }
            return result;
        }

        public static decimal ToDecimal(object input, int? digits = null)
        {
            return ToDecimalOrNull(input, digits) ?? 0m;
        }

        public static decimal? ToDecimalOrNull(object input, int? digits = null)
        {
            decimal num;
            decimal? result;
            if (!decimal.TryParse(input.ToSafeString(), out num))
            {
                result = null;
            }
            else if (digits == null)
            {
                result = new decimal?(num);
            }
            else
            {
                result = new decimal?(Math.Round(num, digits.Value));
            }
            return result;
        }

        public static bool ToBool(object input)
        {
            return ToBoolOrNull(input) ?? false;
        }

        public static bool? ToBoolOrNull(object input)
        {
            bool? @bool = GetBool(input);
            bool? result;
            if (@bool != null)
            {
                result = new bool?(@bool.Value);
            }
            else
            {
                bool value;
                result = bool.TryParse(input.ToSafeString(), out value) ? new bool?(value) : null;
            }
            return result;
        }

        private static bool? GetBool(object input)
        {
            string text = input.ToSafeString().ToLower();
            switch (text)
            {
                case "0":
                    return new bool?(false);

                case "否":
                    return new bool?(false);

                case "不":
                    return new bool?(false);

                case "no":
                    return new bool?(false);

                case "fail":
                    return new bool?(false);

                case "1":
                    return new bool?(true);

                case "是":
                    return new bool?(true);

                case "ok":
                    return new bool?(true);

                case "yes":
                    return new bool?(true);
            }
            return null;
        }

        public static DateTime ToDate(object input)
        {
            return ToDateOrNull(input) ?? DateTime.MinValue;
        }

        public static DateTime? ToDateOrNull(object input)
        {
            DateTime value;
            return DateTime.TryParse(input.ToSafeString(), out value) ? new DateTime?(value) : null;
        }

        public static Guid ToGuid(object input)
        {
            return ToGuidOrNull(input) ?? Guid.Empty;
        }

        public static Guid? ToGuidOrNull(object input)
        {
            Guid value;
            return Guid.TryParse(input.ToSafeString(), out value) ? new Guid?(value) : null;
        }

        public static List<Guid> ToGuidList(string input)
        {
            return ToList<Guid>(input);
        }

        public static List<T> ToList<T>(string input)
        {
            List<T> list = new List<T>();
            List<T> result;
            if (string.IsNullOrWhiteSpace(input))
            {
                result = list;
            }
            else
            {
                string[] source = input.Split(new char[]
                {
                    ','
                });
                list.AddRange(from each in source
                              where !string.IsNullOrWhiteSpace(each)
                              select As<T>(each));
                result = list;
            }
            return result;
        }

        public static T As<T>(object input)
        {
            T result;
            if (input == null)
            {
                result = default;
            }
            else if (input is string && string.IsNullOrWhiteSpace(input.ToString()))
            {
                result = default;
            }
            else
            {
                Type typeFromHandle = typeof(T);
                string a = typeFromHandle.Name.ToLower();
                try
                {
                    if (a == "string")
                    {
                        result = (T)(object)input.ToString();
                    }
                    else if (a == "guid")
                    {
                        result = (T)(object)new Guid(input.ToString());
                    }
                    else if (typeFromHandle.IsEnum)
                    {
                        result = (T)Enum.Parse(typeFromHandle, input.ToSafeString());
                    }
                    else if (input is IConvertible)
                    {
                        result = (T)Convert.ChangeType(input, typeFromHandle);
                    }
                    else
                    {
                        result = (T)input;
                    }
                }
                catch
                {
                    result = default;
                }
            }
            return result;
        }

        public static byte[] ToBytes(string input)
        {
            return ToBytes(input, Encoding.UTF8);
        }

        public static byte[] ToBytes(string input, Encoding encoding)
        {
            return string.IsNullOrWhiteSpace(input) ? new byte[0] : encoding.GetBytes(input);
        }
    }
}